home *** CD-ROM | disk | FTP | other *** search
- Subject: v25i008: trn 2.0 - threaded newsreader based on rn 4.4, Part05/13
- Newsgroups: comp.sources.unix
- Approved: vixie@pa.dec.com
-
- Submitted-by: davison@borland.com (Wayne Davison)
- Posting-number: Volume 25, Issue 8
- Archive-name: trn/part05
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 5 (of 13)."
- # Contents: NEW getdate.y rcln.c search.c sw.c unship.c
- # Wrapped by vixie@cognition.pa.dec.com on Tue Dec 3 16:34:53 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'NEW' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'NEW'\"
- else
- echo shar: Extracting \"'NEW'\" \(11839 characters\)
- sed "s/^X//" >'NEW' <<'END_OF_FILE'
- X TRN 2.0 vs TRN 1.0.3:
- X
- X[If you're upgrading from trn 1.x, at least read the ** LOOK ** section.]
- X
- New commands:
- X
- X g number g command will go to a newsgroup by number where the
- X the number corresponds to that used in the list
- X supplied by the 'L' command. (newsgroup level)
- X z supersede an article (article level)
- X t turn on/off run-time threading for a group that
- X doesn't have a thread file (newsgroup level)
- X A abandon read/unread changes to the current newsgroup
- X (newsgroup level)
- X
- New command-line options:
- X
- X -a use run-time threading to read all groups threaded
- X (even those without a pre-built thread file)
- X -o use the old method of junking articles in the
- X thread commands (they didn't follow the xrefs in
- X trn 1.x)
- X -o2 in addition to -o, don't use the database to make
- X following of xrefs faster. This is useful if your
- X database is maintained by an old version of mthreads
- X (pre-v2.0) -- you'll probably want to put this in
- X the global INIT file if this is true.
- X
- New features:
- X
- X o Trn is now able to thread newsgroups at run-time. This has two
- X implications: it is now possible to maintain a thread database
- X for fewer groups (or none) and still take advantage of the threaded
- X features of trn. Also, when trn is used with a database, it will
- X notice new articles that have not yet been processed by mthreads and
- X incrementally thread them as soon as they arrive. (This means that
- X trn directly reads the active file -- active2 is a private file for
- X mthreads now.)
- X o Trn has much faster and more accurate new-group-finding code that can
- X be used if you (a) run C news, (b) run mthreads with the -t option,
- X or (c) run trrn with a server that: (1) runs C news, (2) runs mthreads
- X with the -t option, or (3) runs acttimes (provided), not mkgrdates.
- X o The 't' command on the newsgroup selection level is used to toggle
- X whether the current group should be read threaded or not. This
- X is especially needed when the entire database does not have thread
- X files, since it allows the user to choose the groups for which they
- X want to have on-the-fly thread data generated. Or use the -a option
- X to force all unthreaded groups to be read as threaded.
- X o Mthreads now keeps track of which articles have xrefs in them so
- X that trn can optimize the junking of articles. This allows all
- X article-junking commands to mark cross-referenced articles as read
- X without a severe speed penalty. (The one exception is 'c'atchup,
- X which does not mark cross-references to keep it compatible.)
- X o The 'e' command will now repeat the previous extraction if it is
- X followed by no options. Thus, you can "e some/long/dir/name" and
- X then use "e" to keep extracting to the same spot. Use "e ." to
- X extract back to the initial default of SAVEDIR.
- X o The uudecoder now understands "include" lines, and only allows a
- X file with the correct 'part' sequence to be decoded next when they
- X are used.
- X o There is now a built-in ship decoder (which is a better uuencode
- X system). They are automatically detected and extracted via the
- X 'e'xtract command.
- X o If you accidentally unsubscribe to a newsgroup, you can now use
- X '-' to get back to it.
- X o The 'a pattern' command to add new newsgroups will now prompt for
- X ALL unsubscribed newsgroups that match the pattern, whether they
- X are in the newsrc file or not.
- X o You can now use the ',' command (mark article and all replies to
- X this article as read) on a search or range command. For example,
- X you can put "/user name/h:," into your KILL file to wipe-out
- X flame-fests started by articles from "user name".
- X o The 'f'ollow-up command (not 'F') has been changed to ask the
- X user if this is a posting that is unrelated to the current article.
- X This automatically clears the References line, sets the Newsgroups
- X line properly, and prompts for the Subject: and Distributions: lines.
- X In other words, all the things that would have been done if the
- X user had remembered to use '$' before starting a new posting.
- X o On entry into a threaded group, trn now marks all missing articles
- X as read. This results in an accurate count when viewing the group
- X at the newsgroup prompt.
- X o Changed the 'q' command in the thread selector to quit the group,
- X not just exit the selector to the article level. Use Esc or '+'
- X for that. See also the HINTS file for a macro to simulate the old
- X behavior.
- X o The newsgroup line is now shown when it conflicts with the current
- X group. This is useful for looking through junk, and noticing groups
- X that have been redirected using C news's '=' directive.
- X
- X
- Slight incompatibility in mthreads: ** LOOK **
- X
- X o Since the -D option in mthreads was busted (it processed all groups
- X instead of only the listed groups), and since people keep expecting
- X "mthreads this.group" to only process one group, I've changed it
- X to work this way. The old behavior of "mthreads comp" (which would
- X process all enabled groups while threading all existing and new comp
- X groups) is achieved by first turning on all of comp with the above
- X command, and then using the command "mthreads -a comp" to process all
- X enabled groups and only add thread files for new comp groups. The
- X usage of the -a option without a hierarchy name hasn't changed --
- X "mthreads -a" will still process all enabled groups and add all new
- X groups (it is equivilent to the command "mthreads -a all"). The
- X command "mthreads all" is a special case that just happens to work
- X the same as before -- it turns on all existing groups, so it also
- X processes all groups. Also, remember that the -n option will skip
- X processing the groups, so that you can use "mthreads -n rec,soc" to
- X turn on all of rec and soc, and then startup an mthreads daemon to
- X do the processing ("mthreads -dave" for example). See the man page
- X (which is now in its proper group: '8') for full details.
- X
- Changes to mthreads:
- X
- X o Mthreads has been enhanced to check its data more fully for file-
- X corruption errors when reading in a thread file. This should
- X almost eliminate the SIGSEV or SIGBUS errors that would terminate
- X mthreads' execution.
- X o Mthreads now has a separate lock file for the daemon and each
- X update pass. This allows you to run an mthreads daemon and still
- X be able to execute single-pass commands when the daemon is sleeping.
- X o The enhanced-expiration code has been improved to run _much_ faster,
- X especially for NNTP versions of mthreads.
- X o Mthreads puts its db.init file into the root of the THREAD_DIR
- X (which might be SPOOL) to make sharing of the data via NFS easier.
- X o Mthreads now has an option to do all its logging using SYSLOG.
- X o Mthreads has some minor optimizations, which should (hopefully)
- X offset the more extensive data checking.
- X o The -s option of mthreads has been extended to allow microseconds
- X to be specified. Using just -s will still delay for one second
- X per article, as will -s1000000. A portable version of usleep is
- X included for sites that lack it.
- X
- X
- New environment variables:
- X AUTOSUBSCRIBE newsgroup pattern for groups to automatically
- X subscribe to when found. Groups not matching
- X are presented to the user via the usual
- X subscription prompts.
- X AUTOUNSUBSCRIBE newsgroup pattern for groups to not subscribe to.
- X Groups matching this pattern are not subsribed to.
- X REPLYTO the value to use for the "Reply-To:" header, if
- X needed.
- X NEWSORG Same as ORGANIZATION. Used for those sites that
- X need ORGANIZATION for other purposes (Apollos).
- X SUPERSEDEHEADER The header format to use for a 'z' command.
- X LOCALTIMEFMT An strftime specification for formatting the
- X local-time output of the date header.
- X
- X
- Bug fixes:
- X
- X o Numbering of sibling articles that arrive out of order has been
- X improved. This is useful for groups like comp.sources.misc that
- X thread common postings as one root article with the rest as
- X immediate children.
- X o Fixed the save command to create intermediate directories. Thus,
- X "s src/newdir/file" will now create newdir instead of complaining.
- X o Fixed a case that could generate a report of negative articles
- X left to read in trn.
- X o Fixed a bug in the thread selector that generated percentages
- X greater than 100%.
- X o The .newsrc-writing code now checks more closely for errors in
- X writing the file, to avoid having zero-length .newsrc's.
- X
- X o NNTP handling has been improved in mthreads. One bug (expecting
- X HEADers received via NNTP to have colons in them) would totally
- X confuse mthreads -- now such bogus header lines are ignored.
- X o If a newsgroup is mentioned twice in the active file, mthreads
- X would process it twice: once with valid arguments, and once with
- X 0 for a high-article count. This would result in a stream of
- X "we've already seen article x" messages, and a negative "Added:"
- X count. It now complains about the bogus group and skips it.
- X
- X o When GETPWENT it defined and an invalid userid is used, an
- X error message is returned. Previously, trn would core dump.
- X o The newsgroups script now knows how to deal with "bogus" newsgroups.
- X (These are groups in the active files marked with status 'x'.)
- X o If there is no news on trn startup and the user enters a "g" at
- X the newsgroup level, the program will now correctly note that
- X no newsgroup name has been entered and reprompt.
- X o Hostnames are now checked without respect to upper/lower case.
- X This fixes a problem with the cancel command (academ.COM != academ.com
- X before the fix).
- X o The NEWSADMIN code was buggy and often didn't work correctly.
- X This has been fixed.
- X o %P is used to find a place for trrn to create active and article
- X files. Previously, /tmp was hardcoded in most places.
- X o newsgroups would not remove the active file copy it made when
- X used via NNTP. Now it does remove this copy when it exits.
- X o Corrected some null pointer problems in the search code. Specifically,
- X entering entering / or ? when there was no previous search pattern
- X would cause a core dump. Now, it tells the user there there is
- X no previous pattern.
- X o trrn now exits and leaves the terminal in a usable state when a
- X server timeout occurs.
- X o trrn now supports the longest lines allowed by the NNTP RFC.
- X o trn will try to preseve permissions on .newsrc when it recreates
- X it. Previously, it didn't do this.
- X o trn deals with NFS timeouts better. If the active file (on an NFS
- X mounted partition) goes away, trn shuts down gracefully now.
- X
- X
- Configure improvements:
- X o Now uses nm to read contents of libc. ar is used if nm fails.
- X o The file config.h is now generated from config.h.SH instead of
- X directly by the Configure script. This allows the config.sh
- X file to be edited (instead of both config.sh and config.h) and
- X then 'make' will re-create config.h.
- X o Configure also provides the option of editing config.sh before
- X config.h and all the shell scripts are created.
- X o Configure stores the origanization name in double quotes in
- X config.sh. This avoids a problem with organization names that
- X have single quotes in them (i.e. many French and Canadian
- X organizations).
- X o Configure now knows about RISC/os, Stardents and uts environments.
- X o Configure allows the specification of a compiler and extra
- X compiler options.
- X o NNTP systems can now specify a system name rather than a filename
- X to read the system name from.
- X
- X
- General improvements:
- X o Makes use of POSIX capabilities if present.
- X o ANSI C Compatible
- X o If __STDC__ is defined, we use the function prototypes.
- X o Hostname may be read in from a file instead of using system calls.
- X o ClariNet news headers are now recognized by trn. All header operations
- X can be done on those headers.
- X o trn will dynamically allocate its structures to cope with any number
- X of newsgroups in .newsrc or the active file.
- X o MMDF is now officially supported as a mail transfer agent.
- END_OF_FILE
- if test 11839 -ne `wc -c <'NEW'`; then
- echo shar: \"'NEW'\" unpacked with wrong size!
- fi
- # end of 'NEW'
- fi
- if test -f 'getdate.y' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'getdate.y'\"
- else
- echo shar: Extracting \"'getdate.y'\" \(12374 characters\)
- sed "s/^X//" >'getdate.y' <<'END_OF_FILE'
- X%token ID MONTH DAY MERIDIAN NUMBER UNIT MUNIT SUNIT ZONE DAYZONE AGO
- X%{
- X /* Steven M. Bellovin (unc!smb) */
- X /* Dept. of Computer Science */
- X /* University of North Carolina at Chapel Hill */
- X /* @(#)getdate.y 2.13 9/16/86 */
- X
- X#include <sys/types.h>
- X#include <ctype.h>
- X#include <time.h>
- X
- X#define NULL 0
- X
- X#define daysec (24L*60L*60L)
- X
- X static int timeflag, zoneflag, dateflag, dayflag, relflag;
- X static time_t relsec, relmonth;
- X static int hh, mm, ss, merid, daylight;
- X static int dayord, dayreq;
- X static int month, day, year;
- X static int ourzone;
- X
- X#define AM 1
- X#define PM 2
- X#define DAYLIGHT 1
- X#define STANDARD 2
- X#define MAYBE 3
- X%}
- X
- X%%
- timedate: /* empty */
- X | timedate item;
- X
- item: tspec =
- X {timeflag++;}
- X | zone =
- X {zoneflag++;}
- X | dtspec =
- X {dateflag++;}
- X | dyspec =
- X {dayflag++;}
- X | rspec =
- X {relflag++;}
- X | nspec;
- X
- nspec: NUMBER =
- X {if (timeflag && dateflag && !relflag) year = $1;
- X else {timeflag++;hh = $1/100;mm = $1%100;ss = 0;merid = 24;}};
- X
- tspec: NUMBER MERIDIAN =
- X {hh = $1; mm = 0; ss = 0; merid = $2;}
- X | NUMBER ':' NUMBER =
- X {hh = $1; mm = $3; merid = 24;}
- X | NUMBER ':' NUMBER MERIDIAN =
- X {hh = $1; mm = $3; merid = $4;}
- X | NUMBER ':' NUMBER NUMBER =
- X {hh = $1; mm = $3; merid = 24;
- X daylight = STANDARD; ourzone = -($4%100 + 60*$4/100);}
- X | NUMBER ':' NUMBER ':' NUMBER =
- X {hh = $1; mm = $3; ss = $5; merid = 24;}
- X | NUMBER ':' NUMBER ':' NUMBER MERIDIAN =
- X {hh = $1; mm = $3; ss = $5; merid = $6;}
- X | NUMBER ':' NUMBER ':' NUMBER NUMBER =
- X {hh = $1; mm = $3; ss = $5; merid = 24;
- X daylight = STANDARD; ourzone = -($6%100 + 60*$6/100);};
- X
- zone: ZONE =
- X {ourzone = $1; daylight = STANDARD;}
- X | DAYZONE =
- X {ourzone = $1; daylight = DAYLIGHT;};
- X
- dyspec: DAY =
- X {dayord = 1; dayreq = $1;}
- X | DAY ',' =
- X {dayord = 1; dayreq = $1;}
- X | NUMBER DAY =
- X {dayord = $1; dayreq = $2;};
- X
- dtspec: NUMBER '/' NUMBER =
- X {month = $1; day = $3;}
- X | NUMBER '/' NUMBER '/' NUMBER =
- X {month = $1; day = $3; year = $5;}
- X | MONTH NUMBER =
- X {month = $1; day = $2;}
- X | MONTH NUMBER ',' NUMBER =
- X {month = $1; day = $2; year = $4;}
- X | NUMBER MONTH =
- X {month = $2; day = $1;}
- X | NUMBER MONTH NUMBER =
- X {month = $2; day = $1; year = $3;};
- X
- X
- rspec: NUMBER UNIT =
- X {relsec += 60L * $1 * $2;}
- X | NUMBER MUNIT =
- X {relmonth += $1 * $2;}
- X | NUMBER SUNIT =
- X {relsec += $1;}
- X | UNIT =
- X {relsec += 60L * $1;}
- X | MUNIT =
- X {relmonth += $1;}
- X | SUNIT =
- X {relsec++;}
- X | rspec AGO =
- X {relsec = -relsec; relmonth = -relmonth;};
- X%%
- X
- static int mdays[12] =
- X {31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
- X#define epoch 1970
- X
- extern struct tm *localtime();
- time_t dateconv(mm, dd, yy, h, m, s, mer, zone, dayflag)
- int mm, dd, yy, h, m, s, mer, zone, dayflag;
- X{
- X time_t tod, jdate;
- X register int i;
- X time_t timeconv();
- X
- X if (yy < 0) yy = -yy;
- X if (yy < 100) yy += 1900;
- X mdays[1] = 28 + (yy%4 == 0 && (yy%100 != 0 || yy%400 == 0));
- X if (yy < epoch || yy > 1999 || mm < 1 || mm > 12 ||
- X dd < 1 || dd > mdays[--mm]) return (-1);
- X jdate = dd-1;
- X for (i=0; i<mm; i++) jdate += mdays[i];
- X for (i = epoch; i < yy; i++) jdate += 365 + (i%4 == 0);
- X jdate *= daysec;
- X jdate += zone * 60L;
- X if ((tod = timeconv(h, m, s, mer)) < 0) return (-1);
- X jdate += tod;
- X if (dayflag==DAYLIGHT || (dayflag==MAYBE&&localtime(&jdate)->tm_isdst))
- X jdate += -1*60*60;
- X return (jdate);
- X}
- X
- time_t dayconv(ord, day, now) int ord, day; time_t now;
- X{
- X register struct tm *loctime;
- X time_t tod;
- X time_t daylcorr();
- X
- X tod = now;
- X loctime = localtime(&tod);
- X tod += daysec * ((day - loctime->tm_wday + 7) % 7);
- X tod += 7*daysec*(ord<=0?ord:ord-1);
- X return daylcorr(tod, now);
- X}
- X
- time_t timeconv(hh, mm, ss, mer) register int hh, mm, ss, mer;
- X{
- X if (mm < 0 || mm > 59 || ss < 0 || ss > 59) return (-1);
- X switch (mer) {
- X case AM: if (hh < 1 || hh > 12) return(-1);
- X return (60L * ((hh%12)*60L + mm)+ss);
- X case PM: if (hh < 1 || hh > 12) return(-1);
- X return (60L * ((hh%12 +12)*60L + mm)+ss);
- X case 24: if (hh < 0 || hh > 23) return (-1);
- X return (60L * (hh*60L + mm)+ss);
- X default: return (-1);
- X }
- X}
- time_t monthadd(sdate, relmonth) time_t sdate, relmonth;
- X{
- X struct tm *ltime;
- X time_t dateconv();
- X time_t daylcorr();
- X int mm, yy;
- X
- X if (relmonth == 0) return 0;
- X ltime = localtime(&sdate);
- X mm = 12*ltime->tm_year + ltime->tm_mon + relmonth;
- X yy = mm/12;
- X mm = mm%12 + 1;
- X return daylcorr(dateconv(mm, ltime->tm_mday, yy, ltime->tm_hour,
- X ltime->tm_min, ltime->tm_sec, 24, ourzone, MAYBE), sdate);
- X}
- X
- time_t daylcorr(future, now) time_t future, now;
- X{
- X int fdayl, nowdayl;
- X
- X nowdayl = (localtime(&now)->tm_hour+1) % 24;
- X fdayl = (localtime(&future)->tm_hour+1) % 24;
- X return (future-now) + 60L*60L*(nowdayl-fdayl);
- X}
- X
- static char *lptr;
- X
- yylex()
- X{
- X extern int yylval;
- X int sign;
- X register char c;
- X register char *p;
- X char idbuf[20];
- X int pcnt;
- X
- X for (;;) {
- X while (isspace(*lptr)) lptr++;
- X
- X if (isdigit(c = *lptr) || c == '-' || c == '+') {
- X if (c== '-' || c == '+') {
- X if (c=='-') sign = -1;
- X else sign = 1;
- X if (!isdigit(*++lptr)) {
- X /* yylval = sign; return (NUMBER); */
- X return yylex(); /* skip the '-' sign */
- X }
- X } else sign = 1;
- X yylval = 0;
- X while (isdigit(c = *lptr++)) yylval = 10*yylval + c - '0';
- X yylval *= sign;
- X lptr--;
- X return (NUMBER);
- X
- X } else if (isalpha(c)) {
- X p = idbuf;
- X while (isalpha(c = *lptr++) || c=='.')
- X if (p < &idbuf[sizeof(idbuf)-1])
- X *p++ = c;
- X *p = '\0';
- X lptr--;
- X return (lookup(idbuf));
- X }
- X
- X else if (c == '(') {
- X pcnt = 0;
- X do {
- X c = *lptr++;
- X if (c == '\0') return(c);
- X else if (c == '(') pcnt++;
- X else if (c == ')') pcnt--;
- X } while (pcnt > 0);
- X }
- X
- X else return (*lptr++);
- X }
- X}
- X
- struct table {
- X char *name;
- X int type, value;
- X};
- X
- struct table mdtab[] = {
- X {"January", MONTH, 1},
- X {"February", MONTH, 2},
- X {"March", MONTH, 3},
- X {"April", MONTH, 4},
- X {"May", MONTH, 5},
- X {"June", MONTH, 6},
- X {"July", MONTH, 7},
- X {"August", MONTH, 8},
- X {"September", MONTH, 9},
- X {"Sept", MONTH, 9},
- X {"October", MONTH, 10},
- X {"November", MONTH, 11},
- X {"December", MONTH, 12},
- X
- X {"Sunday", DAY, 0},
- X {"Monday", DAY, 1},
- X {"Tuesday", DAY, 2},
- X {"Tues", DAY, 2},
- X {"Wednesday", DAY, 3},
- X {"Wednes", DAY, 3},
- X {"Thursday", DAY, 4},
- X {"Thur", DAY, 4},
- X {"Thurs", DAY, 4},
- X {"Friday", DAY, 5},
- X {"Saturday", DAY, 6},
- X {0, 0, 0}};
- X
- X#define HRS *60
- X#define HALFHR 30
- struct table mztab[] = {
- X {"a.m.", MERIDIAN, AM},
- X {"am", MERIDIAN, AM},
- X {"p.m.", MERIDIAN, PM},
- X {"pm", MERIDIAN, PM},
- X {"nst", ZONE, 3 HRS + HALFHR}, /* Newfoundland */
- X {"n.s.t.", ZONE, 3 HRS + HALFHR},
- X {"ast", ZONE, 4 HRS}, /* Atlantic */
- X {"a.s.t.", ZONE, 4 HRS},
- X {"adt", DAYZONE, 4 HRS},
- X {"a.d.t.", DAYZONE, 4 HRS},
- X {"est", ZONE, 5 HRS}, /* Eastern */
- X {"e.s.t.", ZONE, 5 HRS},
- X {"edt", DAYZONE, 5 HRS},
- X {"e.d.t.", DAYZONE, 5 HRS},
- X {"cst", ZONE, 6 HRS}, /* Central */
- X {"c.s.t.", ZONE, 6 HRS},
- X {"cdt", DAYZONE, 6 HRS},
- X {"c.d.t.", DAYZONE, 6 HRS},
- X {"mst", ZONE, 7 HRS}, /* Mountain */
- X {"m.s.t.", ZONE, 7 HRS},
- X {"mdt", DAYZONE, 7 HRS},
- X {"m.d.t.", DAYZONE, 7 HRS},
- X {"pst", ZONE, 8 HRS}, /* Pacific */
- X {"p.s.t.", ZONE, 8 HRS},
- X {"pdt", DAYZONE, 8 HRS},
- X {"p.d.t.", DAYZONE, 8 HRS},
- X {"yst", ZONE, 9 HRS}, /* Yukon */
- X {"y.s.t.", ZONE, 9 HRS},
- X {"ydt", DAYZONE, 9 HRS},
- X {"y.d.t.", DAYZONE, 9 HRS},
- X {"hst", ZONE, 10 HRS}, /* Hawaii */
- X {"h.s.t.", ZONE, 10 HRS},
- X {"hdt", DAYZONE, 10 HRS},
- X {"h.d.t.", DAYZONE, 10 HRS},
- X
- X {"gmt", ZONE, 0 HRS},
- X {"g.m.t.", ZONE, 0 HRS},
- X {"bst", DAYZONE, 0 HRS}, /* British Summer Time */
- X {"b.s.t.", DAYZONE, 0 HRS},
- X {"eet", ZONE, 0 HRS}, /* European Eastern Time */
- X {"e.e.t.", ZONE, 0 HRS},
- X {"eest", DAYZONE, 0 HRS}, /* European Eastern Summer Time */
- X {"e.e.s.t.", DAYZONE, 0 HRS},
- X {"met", ZONE, -1 HRS}, /* Middle European Time */
- X {"m.e.t.", ZONE, -1 HRS},
- X {"mest", DAYZONE, -1 HRS}, /* Middle European Summer Time */
- X {"m.e.s.t.", DAYZONE, -1 HRS},
- X {"wet", ZONE, -2 HRS }, /* Western European Time */
- X {"w.e.t.", ZONE, -2 HRS },
- X {"west", DAYZONE, -2 HRS}, /* Western European Summer Time */
- X {"w.e.s.t.", DAYZONE, -2 HRS},
- X
- X {"jst", ZONE, -9 HRS}, /* Japan Standard Time */
- X {"j.s.t.", ZONE, -9 HRS}, /* Japan Standard Time */
- X /* No daylight savings time */
- X
- X {"aest", ZONE, -10 HRS}, /* Australian Eastern Time */
- X {"a.e.s.t.", ZONE, -10 HRS},
- X {"aesst", DAYZONE, -10 HRS}, /* Australian Eastern Summer Time */
- X {"a.e.s.s.t.", DAYZONE, -10 HRS},
- X {"acst", ZONE, -(9 HRS + HALFHR)}, /* Australian Central Time */
- X {"a.c.s.t.", ZONE, -(9 HRS + HALFHR)},
- X {"acsst", DAYZONE, -(9 HRS + HALFHR)}, /* Australian Central Summer */
- X {"a.c.s.s.t.", DAYZONE, -(9 HRS + HALFHR)},
- X {"awst", ZONE, -8 HRS}, /* Australian Western Time */
- X {"a.w.s.t.", ZONE, -8 HRS}, /* (no daylight time there, I'm told */
- X {0, 0, 0}};
- X
- struct table unittb[] = {
- X {"year", MUNIT, 12},
- X {"month", MUNIT, 1},
- X {"fortnight", UNIT, 14*24*60},
- X {"week", UNIT, 7*24*60},
- X {"day", UNIT, 1*24*60},
- X {"hour", UNIT, 60},
- X {"minute", UNIT, 1},
- X {"min", UNIT, 1},
- X {"second", SUNIT, 1},
- X {"sec", SUNIT, 1},
- X {0, 0, 0}};
- X
- struct table othertb[] = {
- X {"tomorrow", UNIT, 1*24*60},
- X {"yesterday", UNIT, -1*24*60},
- X {"today", UNIT, 0},
- X {"now", UNIT, 0},
- X {"last", NUMBER, -1},
- X {"this", UNIT, 0},
- X {"next", NUMBER, 2},
- X {"first", NUMBER, 1},
- X /* {"second", NUMBER, 2}, */
- X {"third", NUMBER, 3},
- X {"fourth", NUMBER, 4},
- X {"fifth", NUMBER, 5},
- X {"sixth", NUMBER, 6},
- X {"seventh", NUMBER, 7},
- X {"eigth", NUMBER, 8},
- X {"ninth", NUMBER, 9},
- X {"tenth", NUMBER, 10},
- X {"eleventh", NUMBER, 11},
- X {"twelfth", NUMBER, 12},
- X {"ago", AGO, 1},
- X {0, 0, 0}};
- X
- struct table milzone[] = {
- X {"a", ZONE, 1 HRS},
- X {"b", ZONE, 2 HRS},
- X {"c", ZONE, 3 HRS},
- X {"d", ZONE, 4 HRS},
- X {"e", ZONE, 5 HRS},
- X {"f", ZONE, 6 HRS},
- X {"g", ZONE, 7 HRS},
- X {"h", ZONE, 8 HRS},
- X {"i", ZONE, 9 HRS},
- X {"k", ZONE, 10 HRS},
- X {"l", ZONE, 11 HRS},
- X {"m", ZONE, 12 HRS},
- X {"n", ZONE, -1 HRS},
- X {"o", ZONE, -2 HRS},
- X {"p", ZONE, -3 HRS},
- X {"q", ZONE, -4 HRS},
- X {"r", ZONE, -5 HRS},
- X {"s", ZONE, -6 HRS},
- X {"t", ZONE, -7 HRS},
- X {"u", ZONE, -8 HRS},
- X {"v", ZONE, -9 HRS},
- X {"w", ZONE, -10 HRS},
- X {"x", ZONE, -11 HRS},
- X {"y", ZONE, -12 HRS},
- X {"z", ZONE, 0 HRS},
- X {0, 0, 0}};
- X
- lookup(id) char *id;
- X{
- X#define gotit (yylval=i->value, i->type)
- X#define getid for(j=idvar, k=id; *j++ = *k++; )
- X
- X char idvar[20];
- X register char *j, *k;
- X register struct table *i;
- X int abbrev;
- X
- X getid;
- X if (strlen(idvar) == 3) abbrev = 1;
- X else if (strlen(idvar) == 4 && idvar[3] == '.') {
- X abbrev = 1;
- X idvar[3] = '\0';
- X }
- X else abbrev = 0;
- X
- X if (islower(*idvar)) *idvar = toupper(*idvar);
- X
- X for (i = mdtab; i->name; i++) {
- X k = idvar;
- X for (j = i->name; *j++ == *k++;) {
- X if (abbrev && j==i->name+3) return gotit;
- X if (j[-1] == 0) return gotit;
- X }
- X }
- X
- X getid;
- X for (i = mztab; i->name; i++)
- X if (strcmp(i->name, idvar) == 0) return gotit;
- X
- X for (j = idvar; *j; j++)
- X if (isupper(*j)) *j = tolower(*j);
- X for (i=mztab; i->name; i++)
- X if (strcmp(i->name, idvar) == 0) return gotit;
- X
- X getid;
- X for (i=unittb; i->name; i++)
- X if (strcmp(i->name, idvar) == 0) return gotit;
- X
- X if (idvar[strlen(idvar)-1] == 's')
- X idvar[strlen(idvar)-1] = '\0';
- X for (i=unittb; i->name; i++)
- X if (strcmp(i->name, idvar) == 0) return gotit;
- X
- X getid;
- X for (i = othertb; i->name; i++)
- X if (strcmp(i->name, idvar) == 0) return gotit;
- X
- X getid;
- X if (strlen(idvar) == 1 && isalpha(*idvar)) {
- X if (isupper(*idvar)) *idvar = tolower(*idvar);
- X for (i = milzone; i->name; i++)
- X if (strcmp(i->name, idvar) == 0) return gotit;
- X }
- X
- X return(ID);
- X}
- X
- time_t get_date(p, now, zone) char *p; time_t now; long zone;
- X{
- X#define mcheck(f) if (f>1) err++
- X time_t monthadd();
- X int err;
- X struct tm *lt;
- X time_t sdate, tod;
- X
- X lptr = p;
- X if (now <= 0)
- X (void) time(&now);
- X lt = localtime(&now);
- X year = lt->tm_year;
- X month = lt->tm_mon+1;
- X day = lt->tm_mday;
- X relsec = 0; relmonth = 0;
- X timeflag=zoneflag=dateflag=dayflag=relflag=0;
- X daylight = MAYBE;
- X hh = mm = ss = 0;
- X merid = 24;
- X ourzone = zone;
- X
- X if (err = yyparse()) return (-1);
- X
- X mcheck(timeflag);
- X mcheck(zoneflag);
- X mcheck(dateflag);
- X mcheck(dayflag);
- X
- X if (err) return (-1);
- X if (dateflag || timeflag || dayflag) {
- X sdate = dateconv(month,day,year,hh,mm,ss,merid,ourzone,daylight);
- X if (sdate < 0) return -1;
- X }
- X else {
- X sdate = now;
- X if (relflag == 0)
- X sdate -= (lt->tm_sec + lt->tm_min*60 +
- X lt->tm_hour*(60L*60L));
- X }
- X
- X sdate += relsec;
- X sdate += monthadd(sdate, relmonth);
- X
- X if (dayflag && !dateflag) {
- X tod = dayconv(dayord, dayreq, sdate);
- X sdate += tod;
- X }
- X
- X return sdate;
- X}
- X
- yyerror(s) char *s;
- X{}
- END_OF_FILE
- if test 12374 -ne `wc -c <'getdate.y'`; then
- echo shar: \"'getdate.y'\" unpacked with wrong size!
- fi
- # end of 'getdate.y'
- fi
- if test -f 'rcln.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rcln.c'\"
- else
- echo shar: Extracting \"'rcln.c'\" \(13041 characters\)
- sed "s/^X//" >'rcln.c' <<'END_OF_FILE'
- X/* $Id: rcln.c,v 4.4.2.1 1991/12/01 18:05:42 sob PATCH_2 sob $
- X *
- X * $Log: rcln.c,v $
- X * Revision 4.4.2.1 1991/12/01 18:05:42 sob
- X * Patchlevel 2 changes
- X *
- X * Revision 4.4.1.1 1991/09/25 19:38:08 sob
- X * Some adaptions for CNEWS
- X *
- X * Revision 4.4 1991/09/09 20:27:37 sob
- X * release 4.4
- X *
- X *
- X *
- X */
- X/* This software is Copyright 1991 by Stan Barber.
- X *
- X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
- X * use this software as long as: there is no monetary profit gained
- X * specifically from the use or reproduction of this software, it is not
- X * sold, rented, traded or otherwise marketed, and this copyright notice is
- X * included prominently in any copy made.
- X *
- X * The author make no claims as to the fitness or correctness of this software
- X * for any use whatsoever, and it is provided as is. Any use of this software
- X * is at the user's own risk.
- X */
- X
- X#include "EXTERN.h"
- X#include "common.h"
- X#include "util.h"
- X#include "rcstuff.h"
- X#include "ngdata.h"
- X#include "INTERN.h"
- X#include "rcln.h"
- X
- void
- rcln_init()
- X{
- X ;
- X}
- X
- X#ifdef CATCHUP
- void
- catch_up(ngx)
- NG_NUM ngx;
- X{
- X char tmpbuf[128];
- X
- X#ifdef VERBOSE
- X IF(verbose)
- X printf("\nMarking %s as all read.\n",rcline[ngx]) FLUSH;
- X ELSE
- X#endif
- X#ifdef TERSE
- X fputs("\nMarked read\n",stdout) FLUSH;
- X#endif
- X sprintf(tmpbuf,"%s: 1-%ld", rcline[ngx],(long)getngsize(ngx));
- X free(rcline[ngx]);
- X rcline[ngx] = savestr(tmpbuf);
- X *(rcline[ngx] + rcnums[ngx] - 1) = '\0';
- X toread[ngx] = TR_NONE;
- X write_rc();
- X}
- X#endif
- X
- X/* add an article number to a newsgroup, if it isn't already read */
- X
- int
- addartnum(artnum,ngnam)
- ART_NUM artnum;
- char *ngnam;
- X{
- X register NG_NUM ngnum = find_ng(ngnam);
- X register char *s, *t, *maxt = Nullch;
- X ART_NUM min = 0, max = -1, lastnum = 0;
- X char *mbuf;
- X bool morenum;
- X
- X if (!artnum)
- X return 0;
- X if (ngnum == nextrcline || !rcnums[ngnum])
- X /* not found in newsrc? */
- X return 0;
- X#ifdef CACHEFIRST
- X if (!abs1st[ngnum])
- X#else
- X if (!toread[ngnum])
- X#endif
- X#if !defined(SERVER) || defined(MININACT)
- X /* now is a good time to trim down */
- X set_toread(ngnum); /* the list due to expires if we */
- X /* have not yet. */
- X#endif
- X#ifdef DEBUGGING
- X if (artnum > ngmax[ngnum] + 100 /* allow for incoming articles */
- X ) {
- X printf("\nCorrupt Xref line!!! %ld --> %s(1..%ld)\n",
- X artnum,ngnam,
- X ngmax[ngnum]) FLUSH;
- X paranoid = TRUE; /* paranoia reigns supreme */
- X return -1; /* hope this was the first newsgroup */
- X }
- X#endif
- X
- X if (toread[ngnum] == TR_BOGUS)
- X return 0;
- X#ifdef DEBUGGING
- X if (debug & DEB_XREF_MARKER) {
- X printf("%ld->\n%s%c%s\n",(long)artnum,rcline[ngnum],rcchar[ngnum],
- X rcline[ngnum] + rcnums[ngnum]) FLUSH;
- X }
- X#endif
- X s = rcline[ngnum] + rcnums[ngnum];
- X while (*s == ' ') s++; /* skip spaces */
- X t = s;
- X while (isdigit(*s) && artnum >= (min = atol(s))) {
- X /* while it might have been read */
- X for (t = s; isdigit(*t); t++) ; /* skip number */
- X if (*t == '-') { /* is it a range? */
- X t++; /* skip to next number */
- X if (artnum <= (max = atol(t)))
- X return 0; /* it is in range => already read */
- X lastnum = max; /* remember it */
- X maxt = t; /* remember position in case we */
- X /* want to overwrite the max */
- X while (isdigit(*t)) t++; /* skip second number */
- X }
- X else {
- X if (artnum == min) /* explicitly a read article? */
- X return 0;
- X lastnum = min; /* remember what the number was */
- X maxt = Nullch; /* last one was not a range */
- X }
- X while (*t && !isdigit(*t)) t++; /* skip comma and any spaces */
- X s = t;
- X }
- X
- X /* we have not read it, so insert the article number before s */
- X
- X morenum = isdigit(*s); /* will it need a comma after? */
- X#ifdef USETHREADS
- X *(rcline[ngnum] + rcnums[ngnum] - 1) = RCCHAR(rcchar[ngnum]);
- X#else
- X *(rcline[ngnum] + rcnums[ngnum] - 1) = rcchar[ngnum];
- X#endif
- X mbuf = safemalloc((MEM_SIZE)(strlen(s) + (s-rcline[ngnum]) + 8));
- X strcpy(mbuf,rcline[ngnum]); /* make new rc line */
- X if (maxt && lastnum && artnum == lastnum+1)
- X /* can we just extend last range? */
- X t = mbuf + (maxt-rcline[ngnum]);/* then overwrite previous max */
- X else {
- X t = mbuf + (t-rcline[ngnum]); /* point t into new line instead */
- X if (lastnum) { /* have we parsed any line? */
- X if (!morenum) /* are we adding to the tail? */
- X *t++ = ','; /* supply comma before */
- X if (!maxt && artnum == lastnum+1 && *(t-1) == ',')
- X /* adjacent singletons? */
- X *(t-1) = '-'; /* turn them into a range */
- X }
- X }
- X if (morenum) { /* is there more to life? */
- X if (min == artnum+1) { /* can we consolidate further? */
- X bool range_before = (*(t-1) == '-');
- X bool range_after;
- X char *nextmax;
- X
- X for (nextmax = s; isdigit(*nextmax); nextmax++) ;
- X range_after = *nextmax++ == '-';
- X
- X if (range_before)
- X *t = '\0'; /* artnum is redundant */
- X else
- X sprintf(t,"%ld-",(long)artnum);/* artnum will be new min */
- X
- X if (range_after)
- X s = nextmax; /* *s is redundant */
- X /* else
- X s = s */ /* *s is new max */
- X }
- X else
- X sprintf(t,"%ld,",(long)artnum); /* put the number and comma */
- X }
- X else
- X sprintf(t,"%ld",(long)artnum); /* put the number there (wherever) */
- X strcat(t,s); /* copy remainder of line */
- X#ifdef DEBUGGING
- X if (debug & DEB_XREF_MARKER) {
- X printf("%s\n",mbuf) FLUSH;
- X }
- X#endif
- X free(rcline[ngnum]);
- X rcline[ngnum] = mbuf; /* pull the switcheroo */
- X *(rcline[ngnum] + rcnums[ngnum] - 1) = '\0';
- X /* wipe out : or ! */
- X if (toread[ngnum] > TR_NONE) /* lest we turn unsub into bogus */
- X --toread[ngnum];
- X return 0;
- X}
- X
- X#ifdef MCHASE
- X/* delete an article number from a newsgroup, if it is there */
- X
- void
- subartnum(artnum,ngnam)
- register ART_NUM artnum;
- char *ngnam;
- X{
- X register NG_NUM ngnum = find_ng(ngnam);
- X register char *s, *t;
- X register ART_NUM min, max;
- X char *mbuf;
- X int curlen;
- X
- X if (!artnum)
- X return;
- X if (ngnum == nextrcline || !rcnums[ngnum])
- X return; /* not found in newsrc? */
- X#ifdef DEBUGGING
- X if (debug & DEB_XREF_MARKER) {
- X printf("%ld<-\n%s%c%s\n",(long)artnum,rcline[ngnum],rcchar[ngnum],
- X rcline[ngnum] + rcnums[ngnum]) FLUSH;
- X }
- X#endif
- X s = rcline[ngnum] + rcnums[ngnum];
- X while (*s == ' ') s++; /* skip spaces */
- X
- X /* a little optimization, since it is almost always the last number */
- X
- X for (t=s; *t; t++) ; /* find end of string */
- X curlen = t-rcline[ngnum];
- X for (t--; isdigit(*t); t--) ; /* find previous delim */
- X if (*t == ',' && atol(t+1) == artnum) {
- X *t = '\0';
- X if (toread[ngnum] >= TR_NONE)
- X ++toread[ngnum];
- X#ifdef DEBUGGING
- X if (debug & DEB_XREF_MARKER)
- X printf("%s%c %s\n",rcline[ngnum],rcchar[ngnum],s) FLUSH;
- X#endif
- X return;
- X }
- X
- X /* not the last number, oh well, we may need the length anyway */
- X
- X while (isdigit(*s) && artnum >= (min = atol(s))) {
- X /* while it might have been read */
- X for (t = s; isdigit(*t); t++) ; /* skip number */
- X if (*t == '-') { /* is it a range? */
- X t++; /* skip to next number */
- X max = atol(t);
- X while (isdigit(*t)) t++; /* skip second number */
- X if (artnum <= max) {
- X /* it is in range => already read */
- X if (artnum == min) {
- X min++;
- X artnum = 0;
- X }
- X else if (artnum == max) {
- X max--;
- X artnum = 0;
- X }
- X#ifdef USETHREADS
- X *(rcline[ngnum] + rcnums[ngnum] - 1) = RCCHAR(rcchar[ngnum]);
- X#else
- X *(rcline[ngnum] + rcnums[ngnum] - 1) = rcchar[ngnum];
- X#endif
- X mbuf = safemalloc((MEM_SIZE)(curlen + (artnum?15:2)));
- X *s = '\0';
- X strcpy(mbuf,rcline[ngnum]); /* make new rc line */
- X s = mbuf + (s-rcline[ngnum]);
- X /* point s into mbuf now */
- X if (artnum) { /* split into two ranges? */
- X prange(s,min,artnum-1);
- X s += strlen(s);
- X *s++ = ',';
- X prange(s,artnum+1,max);
- X }
- X else /* only one range */
- X prange(s,min,max);
- X s += strlen(s);
- X strcpy(s,t); /* copy remainder over */
- X#ifdef DEBUGGING
- X if (debug & DEB_XREF_MARKER) {
- X printf("%s\n",mbuf) FLUSH;
- X }
- X#endif
- X free(rcline[ngnum]);
- X rcline[ngnum] = mbuf; /* pull the switcheroo */
- X *(rcline[ngnum] + rcnums[ngnum] - 1) = '\0';
- X /* wipe out : or ! */
- X if (toread[ngnum] >= TR_NONE)
- X ++toread[ngnum];
- X return;
- X }
- X }
- X else {
- X if (artnum == min) { /* explicitly a read article? */
- X if (*t == ',') /* pick a comma, any comma */
- X t++;
- X else if (s[-1] == ',')
- X s--;
- X else if (s[-2] == ',') /* (in case of space) */
- X s -= 2;
- X strcpy(s,t); /* no need to realloc */
- X if (toread[ngnum] >= TR_NONE)
- X ++toread[ngnum];
- X#ifdef DEBUGGING
- X if (debug & DEB_XREF_MARKER) {
- X printf("%s%c%s\n",rcline[ngnum],rcchar[ngnum],
- X rcline[ngnum] + rcnums[ngnum]) FLUSH;
- X }
- X#endif
- X return;
- X }
- X }
- X while (*t && !isdigit(*t)) t++; /* skip comma and any spaces */
- X s = t;
- X }
- X}
- X
- void
- prange(where,min,max)
- char *where;
- ART_NUM min,max;
- X{
- X if (min == max)
- X sprintf(where,"%ld",(long)min);
- X else
- X sprintf(where,"%ld-%ld",(long)min,(long)max);
- X}
- X#endif
- X
- X/* calculate the number of unread articles for a newsgroup */
- X
- void
- set_toread(ngnum)
- register NG_NUM ngnum;
- X{
- X register char *s, *c, *h;
- X char tmpbuf[64], *mybuf = tmpbuf;
- X char *nums;
- X int length;
- X#ifdef CACHEFIRST
- X bool virgin_ng = (!abs1st[ngnum]);
- X#endif
- X ART_NUM ngsize = getngsize(ngnum);
- X ART_NUM unread = ngsize;
- X ART_NUM newmax;
- X
- X#if defined(DEBUGGING) || defined(USETHREADS)
- X ngmax[ngnum] = ngsize; /* for checking out-of-range Xrefs */
- X#endif
- X if (ngsize == TR_BOGUS) {
- X printf("\nWarning! Bogus newsgroup: %s\n",rcline[ngnum]) FLUSH;
- X paranoid = TRUE;
- X toread[ngnum] = TR_BOGUS;
- X return;
- X }
- X#ifdef CACHEFIRST
- X if (virgin_ng)
- X#else
- X if (!toread[ngnum])
- X#endif
- X {
- X sprintf(tmpbuf," 1-%ld",(long)ngsize);
- X if (strNE(tmpbuf,rcline[ngnum]+rcnums[ngnum]))
- X checkexpired(ngnum,ngsize); /* this might realloc rcline */
- X }
- X nums = rcline[ngnum]+rcnums[ngnum];
- X length = strlen(nums);
- X if (length >= 60)
- X mybuf = safemalloc((MEM_SIZE)(length+5));
- X strcpy(mybuf,nums);
- X mybuf[length++] = ',';
- X mybuf[length] = '\0';
- X for (s = mybuf; isspace(*s); s++)
- X ;
- X for ( ; (c = index(s,',')) != Nullch ; s = ++c) {
- X /* for each range */
- X *c = '\0'; /* keep index from running off */
- X if ((h = index(s,'-')) != Nullch) /* find - in range, if any */
- X unread -= (newmax = atol(h+1)) - atol(s) + 1;
- X else if (newmax = atol(s))
- X unread--; /* recalculate length */
- X if (newmax > ngsize) { /* paranoia check */
- X unread = -1;
- X break;
- X }
- X }
- X if (unread >= 0) /* reasonable number? */
- X toread[ngnum] = (ART_UNREAD)unread;
- X /* remember how many are left */
- X else { /* SOMEONE RESET THE NEWSGROUP!!! */
- X toread[ngnum] = (ART_UNREAD)ngsize;
- X /* assume nothing carried over */
- X printf("\nWarning! Somebody reset %s--assuming nothing read.\n",
- X rcline[ngnum]) FLUSH;
- X *(rcline[ngnum] + rcnums[ngnum]) = '\0';
- X paranoid = TRUE; /* enough to make a guy paranoid */
- X }
- X if (mybuf != tmpbuf)
- X free(mybuf);
- X if (rcchar[ngnum] == NEGCHAR)
- X toread[ngnum] = TR_UNSUB;
- X}
- X
- X/* make sure expired articles are marked as read */
- X
- void
- checkexpired(ngnum,ngsize)
- register NG_NUM ngnum;
- ART_NUM ngsize;
- X{
- X register ART_NUM a1st = getabsfirst(ngnum,ngsize);
- X register char *s, *t;
- X register ART_NUM num, lastnum = 0;
- X char *mbuf, *newnum;
- X
- X if (a1st<=1)
- X return;
- X#ifdef DEBUGGING
- X if (debug & DEB_XREF_MARKER) {
- X printf("1-%ld->\n%s%c%s\n",(long)(a1st-1),rcline[ngnum],rcchar[ngnum],
- X rcline[ngnum] + rcnums[ngnum]) FLUSH;
- X }
- X#endif
- X for (s = rcline[ngnum] + rcnums[ngnum]; isspace(*s); s++);
- X while (*s && (num = atol(s)) <= a1st) {
- X while (isdigit(*s)) s++;
- X while (*s && !isdigit(*s)) s++;
- X lastnum = num;
- X }
- X if (*s) {
- X if (s[-1] == '-') { /* landed in a range? */
- X if (lastnum != 1) {
- X if (3 + strlen(s) > strlen(rcline[ngnum]+rcnums[ngnum])) {
- X mbuf = safemalloc((MEM_SIZE)(rcnums[ngnum] + 3 +
- X strlen(s) + 1));
- X strcpy(mbuf, rcline[ngnum]);
- X sprintf(mbuf+rcnums[ngnum]," 1-%s",s);
- X free(rcline[ngnum]);
- X rcline[ngnum] = mbuf;
- X } else {
- X sprintf(rcline[ngnum]+rcnums[ngnum]," 1-%s",s);
- X }
- X }
- X goto ret;
- X }
- X }
- X /* s now points to what should follow first range */
- X if (s - rcline[ngnum] > rcnums[ngnum] + 10)
- X mbuf = rcline[ngnum];
- X else {
- X mbuf = safemalloc((MEM_SIZE)(rcnums[ngnum] + strlen(s) + 10));
- X strcpy(mbuf,rcline[ngnum]);
- X }
- X newnum = t = mbuf+rcnums[ngnum];
- X sprintf(t," 1-%ld",(long)(a1st - (lastnum != a1st)));
- X if (*s) {
- X t += strlen(t);
- X *t++ = ',';
- X strcpy(t,s);
- X }
- X if (!checkflag && mbuf == rcline[ngnum]) {
- X rcline[ngnum] = saferealloc(rcline[ngnum],
- X (MEM_SIZE)(rcnums[ngnum] + strlen(newnum) + 1));
- X }
- X else {
- X if (!checkflag)
- X free(rcline[ngnum]);
- X rcline[ngnum] = mbuf;
- X }
- X
- ret:; /* semicolon in case DEBUGGING undefined */
- X#ifdef DEBUGGING
- X if (debug & DEB_XREF_MARKER) {
- X printf("%s%c%s\n",rcline[ngnum],rcchar[ngnum],
- X rcline[ngnum] + rcnums[ngnum]) FLUSH;
- X }
- X#endif
- X}
- X
- END_OF_FILE
- if test 13041 -ne `wc -c <'rcln.c'`; then
- echo shar: \"'rcln.c'\" unpacked with wrong size!
- fi
- # end of 'rcln.c'
- fi
- if test -f 'search.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'search.c'\"
- else
- echo shar: Extracting \"'search.c'\" \(13210 characters\)
- sed "s/^X//" >'search.c' <<'END_OF_FILE'
- X/* $Id: search.c,v 4.4 1991/09/09 20:27:37 sob Exp sob $
- X *
- X * $Log: search.c,v $
- X * Revision 4.4 1991/09/09 20:27:37 sob
- X * release 4.4
- X *
- X *
- X */
- X
- X/* string search routines */
- X
- X/* Copyright (c) 1981,1980 James Gosling */
- X
- X/* Modified Aug. 12, 1981 by Tom London to include regular expressions
- X as in ed. RE stuff hacked over by jag to correct a few major problems,
- X mainly dealing with searching within the buffer rather than copying
- X each line to a separate array. Newlines can now appear in RE's */
- X
- X/* Ripped to shreds and glued back together to make a search package,
- X * July 6, 1984, by Larry Wall. (If it doesn't work, it's probably my fault.)
- X * Changes include:
- X * Buffer, window, and mlisp stuff gone.
- X * Translation tables reduced to 1 table.
- X * Expression buffer is now dynamically allocated.
- X * Character classes now implemented with a bitmap.
- X */
- X
- X#include "EXTERN.h"
- X#include "common.h"
- X#include "util.h"
- X#include "INTERN.h"
- X#include "search.h"
- X
- X#ifndef BITSPERBYTE
- X#define BITSPERBYTE 8
- X#endif
- X
- X#define BMAPSIZ (127 / BITSPERBYTE + 1)
- X
- X/* meta characters in the "compiled" form of a regular expression */
- X#define CBRA 2 /* \( -- begin bracket */
- X#define CCHR 4 /* a vanilla character */
- X#define CDOT 6 /* . -- match anything except a newline */
- X#define CCL 8 /* [...] -- character class */
- X#define NCCL 10 /* [^...] -- negated character class */
- X#define CDOL 12 /* $ -- matches the end of a line */
- X#define CEND 14 /* The end of the pattern */
- X#define CKET 16 /* \) -- close bracket */
- X#define CBACK 18 /* \N -- backreference to the Nth bracketed
- X string */
- X#define CIRC 20 /* ^ matches the beginning of a line */
- X
- X#define WORD 32 /* matches word character \w */
- X#define NWORD 34 /* matches non-word characer \W */
- X#define WBOUND 36 /* matches word boundary \b */
- X#define NWBOUND 38 /* matches non-(word boundary) \B */
- X
- X#define STAR 01 /* * -- Kleene star, repeats the previous
- X REas many times as possible; the value
- X ORs with the other operator types */
- X
- X#define ASCSIZ 0200
- typedef char TRANSTABLE[ASCSIZ];
- X
- static TRANSTABLE trans = {
- X0000,0001,0002,0003,0004,0005,0006,0007,
- X0010,0011,0012,0013,0014,0015,0016,0017,
- X0020,0021,0022,0023,0024,0025,0026,0027,
- X0030,0031,0032,0033,0034,0035,0036,0037,
- X0040,0041,0042,0043,0044,0045,0046,0047,
- X0050,0051,0052,0053,0054,0055,0056,0057,
- X0060,0061,0062,0063,0064,0065,0066,0067,
- X0070,0071,0072,0073,0074,0075,0076,0077,
- X0100,0101,0102,0103,0104,0105,0106,0107,
- X0110,0111,0112,0113,0114,0115,0116,0117,
- X0120,0121,0122,0123,0124,0125,0126,0127,
- X0130,0131,0132,0133,0134,0135,0136,0137,
- X0140,0141,0142,0143,0144,0145,0146,0147,
- X0150,0151,0152,0153,0154,0155,0156,0157,
- X0160,0161,0162,0163,0164,0165,0166,0167,
- X0170,0171,0172,0173,0174,0175,0176,0177,
- X};
- static bool folding = FALSE;
- X
- static int err;
- static char *FirstCharacter;
- X
- void
- search_init()
- X{
- X#ifdef UNDEF
- X register int i;
- X
- X for (i = 0; i < ASCSIZ; i++)
- X trans[i] = i;
- X#else
- X ;
- X#endif
- X}
- X
- void
- init_compex(compex)
- register COMPEX *compex;
- X{
- X /* the following must start off zeroed */
- X
- X compex->eblen = 0;
- X compex->brastr = Nullch;
- X}
- X
- void
- free_compex(compex)
- register COMPEX *compex;
- X{
- X if (compex->eblen) {
- X free(compex->expbuf);
- X compex->eblen = 0;
- X }
- X if (compex->brastr) {
- X free(compex->brastr);
- X compex->brastr = Nullch;
- X }
- X}
- X
- static char *gbr_str = Nullch;
- static int gbr_siz = 0;
- X
- char *
- getbracket(compex,n)
- register COMPEX *compex;
- int n;
- X{
- X int length = compex->braelist[n] - compex->braslist[n];
- X
- X if (!compex->nbra || n > compex->nbra || !compex->braelist[n] || length<0)
- X return nullstr;
- X growstr(&gbr_str, &gbr_siz, length+1);
- X safecpy(gbr_str, compex->braslist[n], length+1);
- X return gbr_str;
- X}
- X
- void
- case_fold(which)
- int which;
- X{
- X register int i;
- X
- X if (which != folding) {
- X if (which) {
- X for (i = 'A'; i <= 'Z'; i++)
- X trans[i] = tolower(i);
- X }
- X else {
- X for (i = 'A'; i <= 'Z'; i++)
- X trans[i] = i;
- X }
- X folding = which;
- X }
- X}
- X
- X/* Compile the given regular expression into a [secret] internal format */
- X
- char *
- compile (compex, strp, RE, fold)
- register COMPEX *compex;
- register char *strp;
- int RE;
- int fold;
- X{
- X register int c;
- X register char *ep;
- X char *lastep;
- X char bracket[NBRA],
- X *bracketp;
- X char **alt = compex->alternatives;
- X char *retmes = "Badly formed search string";
- X
- X case_fold(compex->do_folding = fold);
- X if (!compex->eblen) {
- X compex->expbuf = safemalloc(84);
- X compex->eblen = 80;
- X }
- X ep = compex->expbuf; /* point at expression buffer */
- X *alt++ = ep; /* first alternative starts here */
- X bracketp = bracket; /* first bracket goes here */
- X if (*strp == 0) { /* nothing to compile? */
- X if (*ep == 0) /* nothing there yet? */
- X return "Null search string";
- X return Nullch; /* just keep old expression */
- X }
- X compex->nbra = 0; /* no brackets yet */
- X lastep = 0;
- X for (;;) {
- X if (ep - compex->expbuf >= compex->eblen)
- X grow_eb(compex);
- X c = *strp++; /* fetch next char of pattern */
- X if (c == 0) { /* end of pattern? */
- X if (bracketp != bracket) { /* balanced brackets? */
- X#ifdef VERBOSE
- X retmes = "Unbalanced parens";
- X#endif
- X goto cerror;
- X }
- X *ep++ = CEND; /* terminate expression */
- X *alt++ = 0; /* terminal alternative list */
- X /*
- X compex->eblen = ep - compex->expbuf + 1;
- X compex->expbuf = saferealloc(compex->expbuf,compex->eblen+4); */
- X return Nullch; /* return success */
- X }
- X if (c != '*')
- X lastep = ep;
- X if (!RE) { /* just a normal search string? */
- X *ep++ = CCHR; /* everything is a normal char */
- X *ep++ = c;
- X }
- X else /* it is a regular expression */
- X switch (c) {
- X
- X case '\\': /* meta something */
- X switch (c = *strp++) {
- X case '(':
- X if (compex->nbra >= NBRA) {
- X#ifdef VERBOSE
- X retmes = "Too many parens";
- X#endif
- X goto cerror;
- X }
- X *bracketp++ = ++compex->nbra;
- X *ep++ = CBRA;
- X *ep++ = compex->nbra;
- X break;
- X case '|':
- X if (bracketp>bracket) {
- X#ifdef VERBOSE
- X retmes = "No \\| in parens"; /* Alas! */
- X#endif
- X goto cerror;
- X }
- X *ep++ = CEND;
- X *alt++ = ep;
- X break;
- X case ')':
- X if (bracketp <= bracket) {
- X#ifdef VERBOSE
- X retmes = "Unmatched right paren";
- X#endif
- X goto cerror;
- X }
- X *ep++ = CKET;
- X *ep++ = *--bracketp;
- X break;
- X case 'w':
- X *ep++ = WORD;
- X break;
- X case 'W':
- X *ep++ = NWORD;
- X break;
- X case 'b':
- X *ep++ = WBOUND;
- X break;
- X case 'B':
- X *ep++ = NWBOUND;
- X break;
- X case '0': case '1': case '2': case '3': case '4':
- X case '5': case '6': case '7': case '8': case '9':
- X *ep++ = CBACK;
- X *ep++ = c - '0';
- X break;
- X default:
- X *ep++ = CCHR;
- X if (c == '\0')
- X goto cerror;
- X *ep++ = c;
- X break;
- X }
- X break;
- X case '.':
- X *ep++ = CDOT;
- X continue;
- X
- X case '*':
- X if (lastep == 0 || *lastep == CBRA || *lastep == CKET
- X || *lastep == CIRC
- X || (*lastep&STAR)|| *lastep>NWORD)
- X goto defchar;
- X *lastep |= STAR;
- X continue;
- X
- X case '^':
- X if (ep != compex->expbuf && ep[-1] != CEND)
- X goto defchar;
- X *ep++ = CIRC;
- X continue;
- X
- X case '$':
- X if (*strp != 0 && (*strp != '\\' || strp[1] != '|'))
- X goto defchar;
- X *ep++ = CDOL;
- X continue;
- X
- X case '[': { /* character class */
- X register int i;
- X
- X if (ep - compex->expbuf >= compex->eblen - BMAPSIZ)
- X grow_eb(compex); /* reserve bitmap */
- X for (i = BMAPSIZ; i; --i)
- X ep[i] = 0;
- X
- X if ((c = *strp++) == '^') {
- X c = *strp++;
- X *ep++ = NCCL; /* negated */
- X }
- X else
- X *ep++ = CCL; /* normal */
- X
- X i = 0; /* remember oldchar */
- X do {
- X if (c == '\0') {
- X#ifdef VERBOSE
- X retmes = "Missing ]";
- X#endif
- X goto cerror;
- X }
- X if (*strp == '-' && *(++strp))
- X i = *strp++;
- X else
- X i = c;
- X while (c <= i) {
- X ep[c / BITSPERBYTE] |= 1 << (c % BITSPERBYTE);
- X if (fold && isalpha(c))
- X ep[(c ^ 32) / BITSPERBYTE] |=
- X 1 << ((c ^ 32) % BITSPERBYTE);
- X /* set the other bit too */
- X c++;
- X }
- X } while ((c = *strp++) != ']');
- X ep += BMAPSIZ;
- X continue;
- X }
- X
- X defchar:
- X default:
- X *ep++ = CCHR;
- X *ep++ = c;
- X }
- X }
- cerror:
- X compex->expbuf[0] = 0;
- X compex->nbra = 0;
- X return retmes;
- X}
- X
- void
- grow_eb(compex)
- register COMPEX *compex;
- X{
- X compex->eblen += 80;
- X compex->expbuf = saferealloc(compex->expbuf, (MEM_SIZE)compex->eblen + 4);
- X}
- X
- char *
- execute (compex, addr)
- register COMPEX *compex;
- char *addr;
- X{
- X register char *p1 = addr;
- X register char *trt = trans;
- X register int c;
- X
- X if (addr == Nullch || compex->expbuf == Nullch)
- X return Nullch;
- X if (compex->nbra) { /* any brackets? */
- X for (c = 0; c <= compex->nbra; c++)
- X compex->braslist[c] = compex->braelist[c] = Nullch;
- X if (compex->brastr)
- X free(compex->brastr);
- X compex->brastr = savestr(p1); /* in case p1 is not static */
- X p1 = compex->brastr; /* ! */
- X }
- X case_fold(compex->do_folding); /* make sure table is correct */
- X FirstCharacter = p1; /* for ^ tests */
- X if (compex->expbuf[0] == CCHR && !compex->alternatives[1]) {
- X c = trt[compex->expbuf[1]]; /* fast check for first character */
- X do {
- X if (trt[*p1] == c && advance (compex, p1, compex->expbuf))
- X return p1;
- X p1++;
- X } while (*p1 && !err);
- X return Nullch;
- X }
- X else { /* regular algorithm */
- X do {
- X register char **alt = compex->alternatives;
- X while (*alt) {
- X if (advance (compex, p1, *alt++))
- X return p1;
- X }
- X p1++;
- X } while (*p1 && !err);
- X return Nullch;
- X }
- X /*NOTREACHED*/
- X}
- X
- X/* advance the match of the regular expression starting at ep along the
- X string lp, simulates an NDFSA */
- bool
- advance (compex, lp, ep)
- register COMPEX *compex;
- register char *ep;
- register char *lp;
- X{
- X register char *curlp;
- X register char *trt = trans;
- X register int i;
- X
- X while ((*ep & STAR) || *lp || *ep == CIRC || *ep == CKET)
- X switch (*ep++) {
- X
- X case CCHR:
- X if (trt[*ep++] != trt[*lp]) return FALSE;
- X lp++;
- X continue;
- X
- X case CDOT:
- X if (*lp == '\n') return FALSE;
- X lp++;
- X continue;
- X
- X case CDOL:
- X if (!*lp || *lp == '\n')
- X continue;
- X return FALSE;
- X
- X case CIRC:
- X if (lp == FirstCharacter || lp[-1]=='\n')
- X continue;
- X return FALSE;
- X
- X case WORD:
- X if (isalnum(*lp)) {
- X lp++;
- X continue;
- X }
- X return FALSE;
- X
- X case NWORD:
- X if (!isalnum(*lp)) {
- X lp++;
- X continue;
- X }
- X return FALSE;
- X
- X case WBOUND:
- X if ((lp == FirstCharacter || !isalnum(lp[-1])) !=
- X (!*lp || !isalnum(*lp)) )
- X continue;
- X return FALSE;
- X
- X case NWBOUND:
- X if ((lp == FirstCharacter || !isalnum(lp[-1])) ==
- X (!*lp || !isalnum(*lp)))
- X continue;
- X return FALSE;
- X
- X case CEND:
- X return TRUE;
- X
- X case CCL:
- X if (cclass (ep, *lp, 1)) {
- X ep += BMAPSIZ;
- X lp++;
- X continue;
- X }
- X return FALSE;
- X
- X case NCCL:
- X if (cclass (ep, *lp, 0)) {
- X ep += BMAPSIZ;
- X lp++;
- X continue;
- X }
- X return FALSE;
- X
- X case CBRA:
- X compex->braslist[*ep++] = lp;
- X continue;
- X
- X case CKET:
- X i = *ep++;
- X compex->braelist[i] = lp;
- X compex->braelist[0] = lp;
- X compex->braslist[0] = compex->braslist[i];
- X continue;
- X
- X case CBACK:
- X if (compex->braelist[i = *ep++] == 0) {
- X fputs("bad braces\n",stdout) FLUSH;
- X err = TRUE;
- X return FALSE;
- X }
- X if (backref (compex, i, lp)) {
- X lp += compex->braelist[i] - compex->braslist[i];
- X continue;
- X }
- X return FALSE;
- X
- X case CBACK | STAR:
- X if (compex->braelist[i = *ep++] == 0) {
- X fputs("bad braces\n",stdout) FLUSH;
- X err = TRUE;
- X return FALSE;
- X }
- X curlp = lp;
- X while (backref (compex, i, lp)) {
- X lp += compex->braelist[i] - compex->braslist[i];
- X }
- X while (lp >= curlp) {
- X if (advance (compex, lp, ep))
- X return TRUE;
- X lp -= compex->braelist[i] - compex->braslist[i];
- X }
- X continue;
- X
- X case CDOT | STAR:
- X curlp = lp;
- X while (*lp++ && lp[-1] != '\n');
- X goto star;
- X
- X case WORD | STAR:
- X curlp = lp;
- X while (*lp++ && isalnum(lp[-1]));
- X goto star;
- X
- X case NWORD | STAR:
- X curlp = lp;
- X while (*lp++ && !isalnum(lp[-1]));
- X goto star;
- X
- X case CCHR | STAR:
- X curlp = lp;
- X while (*lp++ && trt[lp[-1]] == trt[*ep]);
- X ep++;
- X goto star;
- X
- X case CCL | STAR:
- X case NCCL | STAR:
- X curlp = lp;
- X while (*lp++ && cclass (ep, lp[-1], ep[-1] == (CCL | STAR)));
- X ep += BMAPSIZ;
- X goto star;
- X
- X star:
- X do {
- X lp--;
- X if (advance (compex, lp, ep))
- X return TRUE;
- X } while (lp > curlp);
- X return FALSE;
- X
- X default:
- X fputs("Badly compiled pattern\n",stdout) FLUSH;
- X err = TRUE;
- X return -1;
- X }
- X if (*ep == CEND || *ep == CDOL) {
- X return TRUE;
- X }
- X return FALSE;
- X}
- X
- bool
- backref (compex, i, lp)
- register COMPEX *compex;
- register int i;
- register char *lp;
- X{
- X register char *bp;
- X
- X bp = compex->braslist[i];
- X while (*lp && *bp == *lp) {
- X bp++;
- X lp++;
- X if (bp >= compex->braelist[i])
- X return TRUE;
- X }
- X return FALSE;
- X}
- X
- bool
- cclass (set, c, af)
- register char *set;
- register int c;
- int af;
- X{
- X c &= 0177;
- X#if BITSPERBYTE == 8
- X if (set[c >> 3] & 1 << (c & 7))
- X#else
- X if (set[c / BITSPERBYTE] & 1 << (c % BITSPERBYTE))
- X#endif
- X return af;
- X return !af;
- X}
- END_OF_FILE
- if test 13210 -ne `wc -c <'search.c'`; then
- echo shar: \"'search.c'\" unpacked with wrong size!
- fi
- # end of 'search.c'
- fi
- if test -f 'sw.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sw.c'\"
- else
- echo shar: Extracting \"'sw.c'\" \(12012 characters\)
- sed "s/^X//" >'sw.c' <<'END_OF_FILE'
- X/* $Id: sw.c,v 4.4 1991/09/09 20:27:37 sob Exp sob $
- X *
- X * $Log: sw.c,v $
- X * Revision 4.4 1991/09/09 20:27:37 sob
- X * release 4.4
- X *
- X *
- X *
- X */
- X/* This software is Copyright 1991 by Stan Barber.
- X *
- X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
- X * use this software as long as: there is no monetary profit gained
- X * specifically from the use or reproduction of this software, it is not
- X * sold, rented, traded or otherwise marketed, and this copyright notice is
- X * included prominently in any copy made.
- X *
- X * The author make no claims as to the fitness or correctness of this software
- X * for any use whatsoever, and it is provided as is. Any use of this software
- X * is at the user's own risk.
- X */
- X
- X#include "EXTERN.h"
- X#include "common.h"
- X#include "util.h"
- X#include "head.h"
- X#include "only.h"
- X#include "term.h"
- X#include "ng.h"
- X#include "intrp.h"
- X#include "INTERN.h"
- X#include "sw.h"
- X
- void
- sw_init(argc,argv,tcbufptr)
- int argc;
- char *argv[];
- char **tcbufptr;
- X{
- X register int i;
- X
- X if (argc >= 2 && strEQ(argv[1],"-c"))
- X checkflag=TRUE; /* so we can optimize for -c */
- X interp(*tcbufptr,1024,GLOBINIT);
- X sw_file(tcbufptr,FALSE);
- X#ifdef USETHREADS
- X if (use_threads)
- X safecpy(*tcbufptr,getval("TRNINIT",getenv("RNINIT")),1024);
- X else
- X#endif
- X safecpy(*tcbufptr,getenv("RNINIT"),1024);
- X if (**tcbufptr) {
- X if (**tcbufptr == '/') {
- X sw_file(tcbufptr,TRUE);
- X }
- X else
- X sw_list(*tcbufptr);
- X }
- X
- X for (i = 1; i < argc; i++)
- X decode_switch(argv[i]);
- X}
- X
- void
- sw_file(tcbufptr,bleat)
- char **tcbufptr;
- bool_int bleat;
- X{
- X int initfd = open(*tcbufptr,0);
- X
- X if (initfd >= 0) {
- X fstat(initfd,&filestat);
- X if (filestat.st_size > 1024)
- X *tcbufptr = saferealloc(*tcbufptr,(MEM_SIZE)filestat.st_size);
- X if (filestat.st_size) {
- X read(initfd,*tcbufptr,(int)filestat.st_size);
- X (*tcbufptr)[filestat.st_size-1] = '\0';
- X /* wipe out last newline */
- X sw_list(*tcbufptr);
- X }
- X else
- X **tcbufptr = '\0';
- X close(initfd);
- X }
- X else {
- X if (bleat)
- X printf(cantopen,*tcbufptr) FLUSH;
- X **tcbufptr = '\0';
- X }
- X}
- X
- X/* decode a list of space separated switches */
- X
- void
- sw_list(swlist)
- char *swlist;
- X{
- X char *tmplist = safemalloc((MEM_SIZE) strlen(swlist) + 2);
- X /* semi-automatic string */
- X register char *p, inquote = 0;
- X
- X strcpy(tmplist,swlist);
- X for (p=tmplist; isspace(*p); p++) ; /* skip any initial spaces */
- X while (*p) { /* "String, or nothing" */
- X if (!inquote && isspace(*p)) { /* word delimiter? */
- X *p++ = '\0'; /* chop here */
- X while (isspace(*p)) /* these will be ignored later */
- X p++;
- X }
- X else if (inquote == *p) {
- X strcpy(p,p+1); /* delete trailing quote */
- X inquote = 0; /* no longer quoting */
- X }
- X else if (!inquote && *p == '"' || *p == '\'') {
- X /* OK, I know when I am not wanted */
- X inquote = *p; /* remember single or double */
- X strcpy(p,p+1); /* delete the quote */
- X } /* (crude, but effective) */
- X else if (*p == '\\') { /* quoted something? */
- X if (p[1] == '\n') /* newline? */
- X strcpy(p,p+2); /* "I didn't see anything" */
- X else {
- X strcpy(p,p+1); /* delete the backwhack */
- X p++; /* leave the whatever alone */
- X }
- X }
- X else
- X p++; /* normal char, leave it alone */
- X }
- X *++p = '\0'; /* put an extra null on the end */
- X if (inquote)
- X printf("Unmatched %c in switch\n",inquote) FLUSH;
- X for (p = tmplist; *p; /* p += strlen(p)+1 */ ) {
- X decode_switch(p);
- X while (*p++) ; /* point at null + 1 */
- X }
- X free(tmplist); /* this oughta be in Ada */
- X}
- X
- X/* decode a single switch */
- X
- void
- decode_switch(s)
- register char *s;
- X{
- X while (isspace(*s)) /* ignore leading spaces */
- X s++;
- X#ifdef DEBUGGING
- X if (debug)
- X printf("Switch: %s\n",s) FLUSH;
- X#endif
- X if (*s != '-' && *s != '+') { /* newsgroup pattern */
- X setngtodo(s);
- X }
- X else { /* normal switch */
- X bool upordown = *s == '-' ? TRUE : FALSE;
- X char tmpbuf[LBUFLEN];
- X
- X s++;
- X switch (*s) {
- X#ifdef TERMMOD
- X case '=': {
- X char *beg = s+1;
- X
- X while (*s && *s != '-' && *s != '+') s++;
- X cpytill(tmpbuf,beg,*s);
- X if (upordown ? strEQ(getenv("TERM"),tmpbuf)
- X : strNE(getenv("TERM"),tmpbuf) ) {
- X decode_switch(s);
- X }
- X break;
- X }
- X#endif
- X#ifdef BAUDMOD
- X case '0': case '1': case '2': case '3': case '4':
- X case '5': case '6': case '7': case '8': case '9':
- X if (upordown ? (just_a_sec*10 <= atoi(s))
- X : (just_a_sec*10 >= atoi(s)) ) {
- X while (isdigit(*s)) s++;
- X decode_switch(s);
- X }
- X break;
- X#endif
- X case '/':
- X if (checkflag)
- X break;
- X#ifdef SETENV
- X setenv("SAVEDIR", upordown ? "%p/%c" : "%p" );
- X setenv("SAVENAME", upordown ? "%a" : "%^C");
- X#else
- X notincl("-/");
- X#endif
- X break;
- X case 'a':
- X#ifdef USETHREADS
- X thread_always = upordown;
- X#else
- X notincl("-a");
- X#endif
- X break;
- X case 'c':
- X checkflag = upordown;
- X break;
- X case 'C':
- X s++;
- X if (*s == '=') s++;
- X docheckwhen = atoi(s);
- X break;
- X case 'd': {
- X if (checkflag)
- X break;
- X s++;
- X if (*s == '=') s++;
- X if (cwd) {
- X chdir(cwd);
- X free(cwd);
- X }
- X cwd = savestr(s);
- X break;
- X }
- X#ifdef DEBUGGING
- X case 'D':
- X s++;
- X if (*s == '=') s++;
- X if (*s)
- X if (upordown)
- X debug |= atoi(s);
- X else
- X debug &= ~atoi(s);
- X else
- X if (upordown)
- X debug |= 1;
- X else
- X debug = 0;
- X break;
- X#endif
- X case 'e':
- X erase_screen = upordown;
- X break;
- X case 'E':
- X#ifdef SETENV
- X s++;
- X if (*s == '=')
- X s++;
- X strcpy(tmpbuf,s);
- X s = index(tmpbuf,'=');
- X if (s) {
- X *s++ = '\0';
- X setenv(tmpbuf,s);
- X }
- X else
- X setenv(tmpbuf,nullstr);
- X#else
- X notincl("-E");
- X#endif
- X break;
- X case 'F':
- X s++;
- X indstr = savestr(s);
- X break;
- X#ifdef INNERSEARCH
- X case 'g':
- X gline = atoi(s+1)-1;
- X break;
- X#endif
- X case 'H':
- X case 'h': {
- X register int len, i;
- X char *t;
- X int flag = (*s == 'h' ? HT_HIDE : HT_MAGIC);
- X
- X if (checkflag)
- X break;
- X s++;
- X len = strlen(s);
- X for (t=s; *t; t++)
- X if (isupper(*t))
- X *t = tolower(*t);
- X for (i=HEAD_FIRST; i<HEAD_LAST; i++)
- X if (!len || strnEQ(s,htype[i].ht_name,len))
- X if (upordown)
- X htype[i].ht_flags |= flag;
- X else
- X htype[i].ht_flags &= ~flag;
- X break;
- X }
- X case 'i':
- X s++;
- X if (*s == '=') s++;
- X initlines = atoi(s);
- X initlines_specified = TRUE;
- X break;
- X case 'l':
- X muck_up_clear = upordown;
- X break;
- X case 'L':
- X#ifdef CLEAREOL
- X can_home_clear = upordown;
- X#else
- X notincl("-L");
- X#endif
- X break;
- X case 'M':
- X mbox_always = upordown;
- X break;
- X case 'm':
- X s++;
- X if (*s == '=') s++;
- X if (!upordown)
- X marking = NOMARKING;
- X else if (*s == 'u')
- X marking = UNDERLINE;
- X else {
- X marking = STANDOUT;
- X }
- X break;
- X case 'N':
- X norm_always = upordown;
- X break;
- X#ifdef VERBOSE
- X case 'n':
- X fputs("This isn't readnews. Don't use -n.\n\n",stdout) FLUSH;
- X break;
- X#endif
- X case 'o':
- X s++;
- X if (*s == '=') s++;
- X if (*s <= '9' && *s >= '0') {
- X olden_days = atoi(s);
- X do {
- X s++;
- X } while (*s <= '9' && *s >= '0');
- X } else
- X olden_days = upordown;
- X break;
- X case 'r':
- X findlast = upordown;
- X break;
- X case 's':
- X s++;
- X if (*s == '=') s++;
- X if (*s) {
- X countdown = atoi(s);
- X suppress_cn = FALSE;
- X }
- X else {
- X if (!upordown)
- X countdown = 5;
- X suppress_cn = upordown;
- X }
- X break;
- X case 'S':
- X#ifdef ARTSEARCH
- X s++;
- X if (*s == '=') s++;
- X if (*s)
- X scanon = atoi(s);
- X else
- X scanon = upordown*3;
- X#else
- X notincl("-S");
- X#endif
- X break;
- X case 't':
- X#ifdef VERBOSE
- X#ifdef TERSE
- X verbose = !upordown;
- X#else
- X notincl("+t");
- X#endif
- X#else
- X notincl("+t");
- X#endif
- X break;
- X case 'T':
- X typeahead = upordown;
- X break;
- X case 'v':
- X#ifdef VERIFY
- X verify = upordown;
- X#else
- X notincl("-v");
- X#endif
- X break;
- X case 'x':
- X#ifdef USETHREADS
- X s++;
- X if (*s == '=') s++;
- X if (*s <= '9' && *s >= '0') {
- X if ((max_tree_lines = atoi(s)) > 11)
- X max_tree_lines = 11;
- X do {
- X s++;
- X } while (*s <= '9' && *s >= '0');
- X } else
- X max_tree_lines = 6;
- X if (*s)
- X strncpy(select_order, s, 3);
- X use_threads = upordown;
- X#else
- X notincl("-x");
- X#endif
- X break;
- X case 'X':
- X#ifdef USETHREADS
- X s++;
- X if (*s == '=') s++;
- X if (*s <= '9' && *s >= '0') {
- X select_on = atoi(s);
- X do {
- X s++;
- X } while (*s <= '9' && *s >= '0');
- X } else
- X select_on = upordown;
- X if (*s)
- X end_select = *s++;
- X if (*s)
- X page_select = *s;
- X#else
- X notincl("-X");
- X#endif
- X break;
- X /*
- X * People want a way to avoid checking for new newsgroups on startup.
- X */
- X case 'q':
- X quickstart = upordown;
- X break;
- X default:
- X#ifdef VERBOSE
- X IF(verbose)
- X printf("\nIgnoring unrecognized switch: -%c\n", *s) FLUSH;
- X ELSE
- X#endif
- X#ifdef TERSE
- X printf("\nIgnoring -%c\n", *s) FLUSH;
- X#endif
- X break;
- X }
- X }
- X}
- X
- X/* print current switch values */
- X
- void
- pr_switches()
- X{
- X static char mp[2] = {'+','-'};
- X register int i;
- X
- X fputs("\nCurrent switch settings:\n",stdout);
- X printf("%c/ ", mp[strEQ(getval("SAVEDIR",SAVEDIR),"%p/%c")]);
- X printf("%ca ", mp[thread_always]);
- X printf("%cc ", mp[checkflag]);
- X printf("-C%d ", docheckwhen);
- X printf("-d%s ", cwd);
- X#ifdef DEBUGGING
- X if (debug)
- X printf("-D%d ", debug);
- X#endif
- X printf("%ce ", mp[erase_screen]);
- X printf("-F\"%s\" ", indstr);
- X#ifdef INNERSEARCH
- X printf("-g%d", gline);
- X#endif
- X putchar('\n');
- X#ifdef VERBOSE
- X if (verbose) {
- X for (i=HEAD_FIRST; i<HEAD_LAST; i++)
- X printf("%ch%s%c",
- X mp[htype[i].ht_flags & HT_HIDE], htype[i].ht_name,
- X (! (i % 5) ? '\n' : ' ') );
- X }
- X#endif
- X printf("-i%d ", initlines);
- X printf("%cl ", mp[muck_up_clear]);
- X#ifdef CLEAREOL
- X printf("%cL ", mp[can_home_clear]);
- X#endif /* CLEAREOL */
- X if (marking)
- X printf("-m%c ",marking==UNDERLINE?'u':'s');
- X else
- X printf("+m ");
- X printf("%cM ", mp[mbox_always]);
- X printf("%cN ", mp[norm_always]);
- X if (olden_days)
- X printf("-o%d ", olden_days);
- X else
- X printf("+o ");
- X printf("%cr ", mp[findlast]);
- X if (countdown)
- X printf("-s%d ", countdown);
- X else
- X printf("%cs ", mp[suppress_cn]);
- X#ifdef ARTSEARCH
- X if (scanon)
- X printf("-S%d ",scanon);
- X else
- X printf("+S ");
- X#endif
- X#ifdef VERBOSE
- X#ifdef TERSE
- X printf("%ct ", mp[!verbose]);
- X#endif
- X#endif
- X printf("%cT ", mp[typeahead]);
- X#ifdef VERIFY
- X printf("%cv ", mp[verify]);
- X#endif
- X#ifdef USETHREADS
- X if (use_threads)
- X printf("-x%d%s ",max_tree_lines,select_order);
- X else
- X printf("+x ");
- X if (select_on)
- X printf("-X%d%c%c ",select_on,end_select,page_select);
- X else
- X printf("+X ");
- X#endif
- X fputs("\n\n",stdout) FLUSH;
- X#ifdef ONLY
- X if (maxngtodo) {
- X#ifdef VERBOSE
- X IF(verbose)
- X fputs("Current restriction:",stdout);
- X ELSE
- X#endif
- X#ifdef TERSE
- X fputs("Only:",stdout);
- X#endif
- X for (i=0; i<maxngtodo; i++)
- X printf(" %s",ngtodo[i]);
- X fputs("\n\n",stdout) FLUSH;
- X }
- X#ifdef VERBOSE
- X else if (verbose)
- X fputs("No restriction.\n\n",stdout) FLUSH;
- X#endif
- X#endif
- X}
- X
- void
- cwd_check()
- X{
- X char tmpbuf[LBUFLEN];
- X
- X if (!cwd)
- X cwd = savestr(filexp("~/News"));
- X strcpy(tmpbuf,cwd);
- X if (chdir(cwd)) {
- X safecpy(tmpbuf,filexp(cwd),sizeof tmpbuf);
- X if (makedir(tmpbuf,MD_DIR) < 0 || chdir(tmpbuf) < 0) {
- X interp(cmd_buf, (sizeof cmd_buf), "%~/News");
- X if (makedir(cmd_buf,MD_DIR) < 0)
- X strcpy(tmpbuf,homedir);
- X else
- X strcpy(tmpbuf,cmd_buf);
- X chdir(tmpbuf);
- X#ifdef VERBOSE
- X IF(verbose)
- X printf("\
- Cannot make directory %s--\n\
- X articles will be saved to %s\n\
- X\n\
- X",cwd,tmpbuf) FLUSH;
- X ELSE
- X#endif
- X#ifdef TERSE
- X printf("\
- Can't make %s--\n\
- X using %s\n\
- X\n\
- X",cwd,tmpbuf) FLUSH;
- X#endif
- X }
- X }
- X free(cwd);
- X getwd(tmpbuf);
- X if (eaccess(tmpbuf,2)) {
- X#ifdef VERBOSE
- X IF(verbose)
- X printf("\
- Current directory %s is not writeable--\n\
- X articles will be saved to home directory\n\n\
- X",tmpbuf) FLUSH;
- X ELSE
- X#endif
- X#ifdef TERSE
- X printf("%s not writeable--using ~\n\n",tmpbuf) FLUSH;
- X#endif
- X strcpy(tmpbuf,homedir);
- X }
- X cwd = savestr(tmpbuf);
- X}
- END_OF_FILE
- if test 12012 -ne `wc -c <'sw.c'`; then
- echo shar: \"'sw.c'\" unpacked with wrong size!
- fi
- # end of 'sw.c'
- fi
- if test -f 'unship.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'unship.c'\"
- else
- echo shar: Extracting \"'unship.c'\" \(11690 characters\)
- sed "s/^X//" >'unship.c' <<'END_OF_FILE'
- X/* unship.c -- for unpacking ship files via trn */
- X/* Based on ship.c -- Not copyrighted 1991 Mark Adler. */
- X/* Modified by Wayne Davison, but still not copyrighted. */
- X
- X#include "EXTERN.h"
- X#include "common.h"
- X#include "respond.h"
- X#include "decode.h"
- X
- typedef unsigned long ulg; /* 32-bit unsigned integer */
- X
- X/* Function prototypes */
- X
- static void decode_line ANSI((unsigned char *));
- static void err ANSI((int));
- X
- X/* Globals for ship() */
- ulg ccnt; /* count of bytes read or written */
- ulg crc; /* CRC register */
- ulg buf4; /* four byte buffer */
- int bcnt; /* buffer count */
- X
- unsigned int decb; /* bit buffer for decode */
- unsigned int decn; /* number of bits in decb */
- X
- bool fast; /* true for arithmetic coding, else base 85 */
- bool overwrite = 1; /* should we overwrite existing files? */
- X
- X/* Errors */
- X#define SE_FORM 1
- X#define SE_CONT 2
- X#define SE_CRC 3
- X#define SE_OVER 4
- X#define SE_FULL 5
- char *errors[] = {
- X /* 1 */ "Invalid ship format.",
- X /* 2 */ "This piece is out of sequence.",
- X /* 3 */ "CRC check failed.",
- X /* 4 */ "File already exists.",
- X /* 5 */ "Error writing file.",
- X};
- X
- X/* Set of 86 characters used for the base 85 digits (last one not used), and
- X the 86 character arithmetic coding. Selected to be part of both the ASCII
- X printable characters, and the common EBCDIC printable characters whose
- X ASCII translations are universal. */
- unsigned char safe[] = {
- X '{','"','#','$','%','&','\'','(',')','*','+',',','-','.','/',
- X '0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?','@',
- X 'A','B','C','D','E','F','G','H','I','J','K','L','M',
- X 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_',
- X 'a','b','c','d','e','f','g','h','i','j','k','l','m',
- X 'n','o','p','q','r','s','t','u','v','w','x','y','z','}'};
- X
- X#define LOWSZ (sizeof(safe)-64) /* low set size for fast coding */
- X
- X/* Special replacement pairs--if first of each pair is received, it is
- X treated like the second member of the pair. You're probably
- X wondering why. The first pair is for compatibility with an
- X earlier version of ship that used ! for the base 85 zero digit.
- X However, there exist ASCII-EBCDIC translation tables that don't
- X know about exclamation marks. The second set has mysterious
- X historical origins that are best left unspoken ... */
- unsigned char aliases[] = {'!','{','|','+',0};
- X
- X/* Inverse of safe[], filled in by unship_init() */
- unsigned char invsafe[256];
- X
- X/* Table of CRC-32's of all single byte values (made by makecrc.c) */
- ulg crctab[] = {
- X 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
- X 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
- X 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
- X 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
- X 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
- X 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
- X 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
- X 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
- X 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
- X 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
- X 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
- X 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
- X 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
- X 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
- X 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
- X 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
- X 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
- X 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
- X 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
- X 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
- X 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
- X 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
- X 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
- X 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
- X 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
- X 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
- X 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
- X 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
- X 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
- X 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
- X 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
- X 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
- X 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
- X 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
- X 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
- X 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
- X 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
- X 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
- X 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
- X 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
- X 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
- X 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
- X 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
- X 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
- X 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
- X 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
- X 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
- X 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
- X 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
- X 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
- X 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
- X 0x2d02ef8dL
- X};
- X
- X/* Macro to update the CRC shift register one byte at a time */
- X#define CRC(c,b) (crctab[((int)(c)^(int)(b))&0xff]^((c)>>8))
- X
- X/* cputc(d,x)--like putc(d,f), but delays four bytes and computes a CRC.
- X x is a cfile *, and d is expected to be an ulg. */
- X#define cputf(fp) (int)(crc=CRC(crc,buf4),putc((int)buf4&0xff,fp),ccnt++)
- X#define cputc(d,fp) (bcnt!=4?bcnt++:cputf(fp),buf4=(buf4>>8)+((ulg)(d)<<24))
- X
- X/* Build invsafe[], the inverse of safe[]. */
- void
- unship_init()
- X{
- X int i;
- X
- X for (i = 0; i < 256; i++)
- X invsafe[i] = 127;
- X for (i = 0; i < sizeof(safe); i++)
- X invsafe[safe[i]] = (char)i;
- X for (i = 0; aliases[i]; i += 2)
- X invsafe[aliases[i]] = invsafe[aliases[i + 1]];
- X}
- X
- int
- unship(in)
- XFILE *in;
- X{
- X int b; /* state of line loop */
- X char l[LBUFLEN]; /* line buffer on input */
- X char *p; /* modifies line buffer */
- X char *q; /* scans continuation line */
- X
- X /* Loop on the latest article's lines */
- X b = 2; /* not in body yet */
- X while (1) /* return on end of last file */
- X {
- X /* Get next line from file */
- X if (fgets(l, LBUFLEN, in) == Nullch)
- X break;
- X
- X /* Strip control characters and leading blank space, if any */
- X for (q = l; *q && *q <= ' ' && *q != '\n'; q++)
- X ;
- X for (p = l; *q; q++)
- X if (*q >= ' ' || *q == '\n')
- X *p++ = *q;
- X *p = 0;
- X
- X /* Based on current state, end or start on terminator. States are:
- X b == 0: at start of body or body terminator line
- X b == 1: in middle of body line
- X b == 2: at start of non-body line
- X b == 3: in middle of non-body line
- X b == 4: at information line
- X */
- X switch (b)
- X {
- X case 0:
- X if ((!fast && strEQ(l, "$\n")) ||
- X (fast && strEQ(l, "$ f\n")))
- X {
- X b = 4;
- X break;
- X }
- X /* fall through to case 1 */
- X case 1:
- X decode_line((unsigned char *)l);
- X b = l[strlen(l) - 1] != '\n';
- X break;
- X case 2:
- X if (strEQ(l, "$\n") || strEQ(l, "$ f\n"))
- X {
- X fast = l[1] == ' ';
- X b = 4;
- X break;
- X }
- X /* fall through to case 3 */
- X case 3:
- X b = l[strlen(l)-1] == '\n' ? 2 : 3;
- X break;
- X case 4:
- X /* Possible information lines are ship, more, cont, and end */
- X if (l[b = strlen(l) - 1] != '\n')
- X {
- X err(SE_FORM);
- X decode_end();
- X return -1;
- X }
- X l[b] = 0;
- X if (strnEQ(l, "ship ", 5))
- X {
- X /* get name, open new output file */
- X if (decode_fp != Nullfp)
- X decode_end(); /* outputs an "incomplete" warning */
- X if (strEQ(l + 5, "-"))
- X strcpy(decode_fname, "unnamed");
- X else
- X strcpy(decode_fname, l + 5);
- X sprintf(decode_dest, "%s/%s", extractdest, decode_fname);
- X printf("Decoding: %s\n", decode_fname);
- X#ifndef VMS /* shouldn't have explicit version #, so VMS won't overwrite */
- X if (!overwrite && (decode_fp = fopen(decode_dest, "r")) != Nullfp)
- X {
- X fclose(decode_fp);
- X decode_fp = Nullfp;
- X err(SE_OVER);
- X return -1;
- X }
- X#endif /* !VMS */
- X if ((decode_fp = fopen(decode_dest, FOPEN_WB)) == Nullfp)
- X {
- X err(SE_FULL);
- X return -1;
- X }
- X crc = 0xffffffffL; /* preload CRC register */
- X buf4 = 0; /* empty fifo (for output) */
- X bcnt = 0; /* fifo is empty (output) */
- X b = decb = decn = 0;
- X ccnt = 0;
- X }
- X else if (strEQ(l, "more"))
- X {
- X /* check if currently writing */
- X if (decode_fp == Nullfp)
- X {
- X err(SE_FORM);
- X return -1;
- X }
- X b = 2;
- X }
- X else if (strnEQ(l, "cont ", 5))
- X {
- X /* check name and file offset */
- X if (decode_fp == Nullfp)
- X {
- X err(SE_CONT);
- X return -1;
- X }
- X for (q = l + 5; *q && *q != ' '; q++)
- X ;
- X if (*q == 0 || atol(l + 5) != ccnt + 4 + (decn != 0) ||
- X strNE(q + 1, decode_fname))
- X {
- X err(SE_CONT);
- X return -1;
- X }
- X b = 0;
- X }
- X else if (strcmp(l, "end") == 0)
- X {
- X /* check crc, close output file */
- X if (decode_fp == Nullfp)
- X {
- X err(SE_FORM);
- X return -1;
- X }
- X if (bcnt != 4 || buf4 != ~crc)
- X err(SE_CRC);
- X else
- X printf("CRC verified -- Done.\n");
- X if (ferror(decode_fp) || fclose(decode_fp))
- X {
- X err(SE_FULL);
- X decode_end();
- X return -1;
- X }
- X decode_fp = Nullfp;
- X b = 2;
- X }
- X else
- X {
- X for (q = l; *q && *q != ' '; q++)
- X ;
- X *q = 0;
- X printf("Ignoring unsupported ship keyword: '%s'\n", l);
- X b = 4;
- X }
- X break;
- X }
- X }
- X if (!(b & 2)) {
- X err(SE_FORM);
- X return -1;
- X }
- X if (decode_fp)
- X printf("(Continued)\n");
- X return 0;
- X}
- X
- X/* Decode s, a string of base 85 digits or, if fast is true, a string of safe
- X characters generated arithmetically, into its binary equivalent, writing
- X the result to decode_fp, using cputc(). */
- static void
- decode_line(s)
- unsigned char *s; /* data to decode */
- X{
- X int b; /* state of line loop, next character */
- X int k; /* counts bits or digits read */
- X /* powers of 85 table for decoding */
- X static ulg m[] = {1L,85L,85L*85L,85L*85L*85L,85L*85L*85L*85L};
- X
- X if (fast)
- X {
- X unsigned int d; /* disperses bits */
- X
- X d = decb;
- X k = decn;
- X while ((b = *s++) != 0)
- X if ((b = invsafe[b]) < sizeof(safe))
- X {
- X if (b < LOWSZ)
- X {
- X d |= b << k;
- X k += 7;
- X }
- X else if ((b -= LOWSZ) < LOWSZ)
- X {
- X d |= (b + 0x40) << k;
- X k += 7;
- X }
- X else
- X {
- X d |= b << k;
- X k += 6;
- X }
- X if (k >= 8)
- X {
- X cputc(d, decode_fp);
- X d >>= 8;
- X k -= 8;
- X }
- X }
- X decb = d;
- X decn = k;
- X }
- X else
- X {
- X ulg d; /* disperses bytes */
- X
- X d = k = 0;
- X while ((b = *s++) != 0)
- X if ((b = invsafe[b]) < 85)
- X {
- X d += m[k] * b;
- X if (++k == 5)
- X {
- X cputc(d, decode_fp); d >>= 8;
- X cputc(d, decode_fp); d >>= 8;
- X cputc(d, decode_fp); d >>= 8;
- X cputc(d, decode_fp);
- X d = k = 0;
- X }
- X }
- X if (--k > 0)
- X {
- X while (--k)
- X {
- X cputc(d, decode_fp);
- X d >>= 8;
- X }
- X cputc(d, decode_fp);
- X }
- X }
- X}
- X
- static void
- err(n)
- int n; /* error number */
- X{
- X if (n == SE_FULL)
- X perror("ship");
- X fputs(errors[n - 1], stdout);
- X putchar('\n') FLUSH;
- X}
- END_OF_FILE
- if test 11690 -ne `wc -c <'unship.c'`; then
- echo shar: \"'unship.c'\" unpacked with wrong size!
- fi
- # end of 'unship.c'
- fi
- echo shar: End of archive 5 \(of 13\).
- cp /dev/null ark5isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 13 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-